package com.bugsnag.android

internal class ErrorInternal @JvmOverloads internal constructor(
    var errorClass: String,
    var errorMessage: String?,
    stacktrace: Stacktrace,
    var type: ErrorType = ErrorType.ANDROID
) : JsonStream.Streamable {

    val stacktrace: MutableList<Stackframe> = stacktrace.trace

    fun addStackframe(method: String?, file: String?, lineNumber: Long): Stackframe {
        val frame = Stackframe(method, file, lineNumber, null)
        stacktrace.add(frame)
        return frame
    }

    internal companion object {
        fun createError(
            exc: Throwable,
            projectPackages: Collection<String>,
            captureStacktrace: Boolean,
            logger: Logger
        ): MutableList<Error> {
            return exc.safeUnrollCauses()
                .mapTo(mutableListOf()) { currentEx ->
                    // Somehow it's possible for stackTrace to be null in rare cases
                    val stacktrace: Array<StackTraceElement> =
                        if (captureStacktrace) {
                            currentEx.stackTrace ?: emptyArray<StackTraceElement>()
                        } else {
                            emptyArray<StackTraceElement>()
                        }
                    val trace = Stacktrace(stacktrace, projectPackages, logger)
                    val errorInternal = ErrorInternal(
                        currentEx.javaClass.name,
                        currentEx.localizedMessage,
                        trace
                    )

                    return@mapTo Error(errorInternal, logger)
                }
        }
    }

    override fun toStream(writer: JsonStream) {
        writer.beginObject()
        writer.name("errorClass").value(errorClass)
        writer.name("message").value(errorMessage)
        writer.name("type").value(type.desc)
        writer.name("stacktrace").value(stacktrace)
        writer.endObject()
    }
}
